home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Resources / Chat & Communication / PeerAware 1.03 / PeerAware-Setup.exe / Html / scripts / vmlrenderer.js < prev   
Text File  |  2008-09-07  |  68KB  |  2,434 lines

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  
  3. This code has been relicensed under LGPL as permitted by original license.
  4.  
  5. Copyright Cumulate Draw Editor
  6.  
  7. This library is free software; you can redistribute it and/or
  8. modify it under the terms of the GNU Lesser General Public
  9. License as published by the Free Software Foundation; either
  10. version 2.1 of the License, or (at your option) any later version.
  11.  
  12. This library is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15. Lesser General Public License for more details.
  16.  
  17. You should have received a copy of the GNU Lesser General Public
  18. License along with this library; if not, write to the Free Software
  19. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA 
  20.  * ***** END LICENSE BLOCK ***** */
  21. /**
  22.  * VML Renderer is responsible for all low level rendering operations associated with rendering for IE
  23.  */
  24.  
  25. function VMLRenderer() {
  26.     this.base = AbstractRenderer;
  27.     
  28.     
  29. }
  30.  
  31.  
  32. VMLRenderer.prototype = new AbstractRenderer;
  33.  
  34. /**
  35. *initialize the renderer
  36. *@param editor element
  37. **/
  38. VMLRenderer.prototype.init = function(elem) {
  39.   this.container = elem;
  40.   
  41.   this.container.style.overflow = 'hidden';
  42.   this.screenXDPI=screen.logicalXDPI / 72;
  43.   this.COORD_X=1000;
  44.   this.COORD_Y=1000;
  45.     // Add VML includes and namespace
  46.   elem.ownerDocument.namespaces.add("v", "urn:schemas-microsoft-com:vml");
  47.   elem.ownerDocument.namespaces.add("c", "urn:schemas-cumulatelabs-com:draw");
  48.   var style = elem.ownerDocument.createStyleSheet();
  49.   style.addRule('v\\:*', "behavior: url(#default#VML);");
  50.   this.minIndex=200;
  51.   this.maxIndex=200;
  52.   this.CONNECTOR_TAG='connector';
  53.   this.LINE_DELIMITER="\r\n";
  54.   this.EXTENSION='mmd';
  55.   this.TYPE="VML";
  56.   this.LONG_DASH="longdash";
  57.   this.SHORT_DASH="dash";
  58.   this.SOLID_DASH="solid";
  59.   
  60.     
  61. }
  62.  
  63.  
  64. /**
  65. *get the id and bounds of the shape, if its a connector return the x,y,x2,y2 for it
  66. **/
  67.  
  68. VMLRenderer.prototype.bounds = function(shape) {
  69.    if(!shape)return;
  70.   var rect = { x:0, y:0, width:0, height: 0,rotation:0,x2:0,y2:0,id:0,type:"",controlX:0,controlY:0,controlX2:0,controlY2:0 };
  71.   rect['id']=shape.getAttribute("id");
  72.   if(this.isConnector(shape))
  73.   {
  74.       rect['x']=this.pointToPixel(this.getConnectorFromX(shape));
  75.       rect['y']=this.pointToPixel(this.getConnectorFromY(shape));
  76.       rect['x2']=this.pointToPixel(this.getConnectorToX(shape));
  77.       rect['y2']=this.pointToPixel(this.getConnectorToY(shape));
  78.       rect['type']=this.getConnectorType(shape);
  79.       if(rect.type=='curve-line'){
  80.           var obj1=this.getControl1(shape);
  81.           var obj2=this.getControl2(shape);
  82.           rect['controlX']=obj1.x;
  83.           rect['controlY']=obj1.y;
  84.           rect['controlX2']=obj2.x;
  85.           rect['controlY2']=obj2.y;
  86.       }
  87.       
  88.   }
  89.   else{
  90.  
  91.     var rotation=shape.style.rotation;
  92.     rect['rotation']=shape.style.rotation;
  93.     if(!rect['rotation'])
  94.         rect['rotation']=0;
  95.     shape.style.rotation=0;
  96.     rect['x']=shape.style.left.split("px")[0];
  97.     rect['y']=shape.style.top.split("px")[0];
  98.     rect['width'] =  (shape.style.width.split("px")[0]*1);
  99.     rect['height'] = (shape.style.height.split("px")[0]*1);
  100.     rect['left']=shape.offsetLeft;
  101.     rect['top']=shape.offsetTop;
  102.     shape.style.rotation=rotation;
  103.   }
  104.   return rect;
  105. }
  106. /**
  107. * a utility function to convert points to pixels
  108. **/
  109. VMLRenderer.prototype.pointToPixel=function(point){
  110.     if(!point||point.length==0)return 0;
  111.     return (point*1)*this.screenXDPI;
  112. }
  113. /**
  114. * a utitlity function to return an attribute in IE specific manner,assumes that element is not null
  115. *@param element
  116. *@param attribute name
  117. **/
  118. VMLRenderer.prototype.getAttribute=function(element,attribute){
  119.     return element.getAttribute(attribute);
  120.  
  121. }
  122. /************************************SHAPE CREATION FUNCTIONS**************************/
  123. /**
  124. *load an xml shape for creation-
  125. *TODO we will have to add some error handling later on
  126. */
  127.  
  128. VMLRenderer.prototype.loadShape=function(shapeID,retrieveTag){
  129.     
  130.     var objValidXMLFile=this.loadXML("shapes/vml/"+shapeID+".xml");
  131.     var nodeList=objValidXMLFile.getElementsByTagName(retrieveTag);
  132.     if(retrieveTag){
  133.         var node=nodeList[0];
  134.         return node;
  135.     }
  136.  
  137. }
  138.  
  139. VMLRenderer.prototype.loadXML=function(path){
  140.     objValidXMLFile = new ActiveXObject("Microsoft.XMLDOM");
  141.     objValidXMLFile.async=false;
  142.     objValidXMLFile.load(path);
  143.     return objValidXMLFile;
  144. }
  145. /**
  146. *load the orthogonal or line connector shape, the type (ortho or line) is determined by shape
  147. *
  148. **/
  149. VMLRenderer.prototype.createLine=function(shape,lineColor,lineWidth,left,top,lineStyle){
  150.     
  151.     doc=this.container.ownerDocument;
  152.     var vml=null;
  153.     var load=this.loadShape(shape,"c:connector");
  154.     var dummy = doc.createElement("div");
  155.     dummy.insertAdjacentHTML("AfterBegin", load.xml);
  156.     var parent = dummy.firstChild;
  157.     
  158.     vml=this.getShapeSubject(parent);
  159.     if(shape=='line'){
  160.         vml.setAttribute("from",left+"px,"+top+"px");
  161.         vml.setAttribute("to",left+"px,"+top+"px");
  162.     }
  163.     else if(shape=='ortho-line'){
  164.         vml.points.value="0,0";
  165.     }
  166.     else{//this is a curve
  167.         vml.from="0,0";
  168.         vml.to="0,0";
  169.         vml.control1="1,1"
  170.         vml.control2="1,1";
  171.     }
  172.     vml.strokeweight=lineWidth;
  173.     vml.strokecolor=lineColor;
  174.     
  175.     this.container.appendChild(parent);
  176.     vml.style.zIndex=this.maxIndex++;
  177.     this.setLineStyle(parent,lineStyle);
  178.     
  179.     return parent;
  180.  
  181. }
  182. /**
  183. *indicate if the given shape is a connector
  184. **/
  185. VMLRenderer.prototype.isConnector=function(shape){
  186.     if(shape)
  187.         return (shape.tagName==this.CONNECTOR_TAG);
  188.     else return false;
  189. }
  190. /**
  191. *create a grouped shape and set properties on the group instead of the shape
  192. **/
  193.  
  194. VMLRenderer.prototype.create = function(shape, fillColor, lineColor, lineWidth, left, top, width, height,opacity,gradient,shadow) {
  195.   
  196.     var rect;
  197.     doc=this.container.ownerDocument;
  198.     var vml=null;
  199.     var load=this.loadShape(shape,"v:group");
  200.     var dummy = doc.createElement("div");
  201.     dummy.insertAdjacentHTML("AfterBegin", load.xml);
  202.     vml = dummy.firstChild;
  203.     //first set the Z-index;
  204.     vml.style.zIndex=this.maxIndex++;
  205.     vml.style.rotation=0;
  206.     if (shape != 'line') {  
  207.         vml.style.position = 'absolute';
  208.         vml.style.left = left;
  209.         vml.style.top = top;
  210.         vml.style.width = width;
  211.         vml.style.height = height;
  212.  
  213.     }
  214.    
  215.       if(opacity!=''){
  216.           this.setOpacity(vml,opacity);
  217.       }
  218.       //if(gradient!=''){
  219.           //this.setGradient(vml,gradient);
  220.       //}
  221.       if(shadow!=''){
  222.           this.setShadow(vml,shadow);
  223.       }
  224.   this.container.appendChild(vml);
  225.   return vml;
  226. };
  227.  
  228. /**
  229. * we had to introduce a hack for vml polylines, see savePolyLinePath for explanation
  230. * @param shape
  231. **/
  232. VMLRenderer.prototype.copy=function(shape){
  233.     if(!shape)return null;
  234.     
  235.         if(this.isConnector(shape)){
  236.             type=this.getConnectorType(shape);
  237.             if(type!='line'&&type!='curve-line'){
  238.                 this.savePolyLinePath(shape);
  239.             }
  240.         }
  241.     return  shape.outerHTML;
  242.  
  243. }
  244.  
  245. /**
  246. * 06.01.2008 Jonny Rein: Added keepID, it is used to keep the same ID for the objects across 
  247. * different instances of a synced drawing.
  248. **/
  249. VMLRenderer.prototype.paste=function(shape,keepID){
  250.         if(!shape)return;
  251.         //get the outher html from clipboard and add it to div
  252.         var dummy = this.container.ownerDocument.createElement("div");
  253.         dummy.insertAdjacentHTML("AfterBegin", shape);
  254.         var node = dummy.firstChild;
  255.         var origId=node.id;
  256.         if (!keepID)
  257.             node.id='shape:' + createUUID();
  258.  
  259.         if(!this.isConnector(node) && !keepID){
  260.             node.style.top=(node.style.top.split('px')[0]*1+10)+"px";
  261.             node.style.left=(node.style.left.split('px')[0]*1+10)+"px";
  262.         }
  263.         //now null any connections
  264.         var connectList=node.getElementsByTagName("connection");
  265.         var array=new Array();
  266.         for(var i=0;i<connectList.length;i++){
  267.             //if its a line emtpy it
  268.             if(node.tagName=='connector'){
  269.                 connectList.item(i).setAttribute("shapeid","xx");
  270.                 connectList.item(i).setAttribute("shapepoint","-1");
  271.             }
  272.             //if its a shape remove it!
  273.             else{
  274.              array[i]=connectList.item(i);
  275.             }
  276.         }
  277.         for(var i=0;i<array.length;i++){
  278.             array[i].removeNode(true);
  279.         }
  280.         
  281.         
  282.         //IE hack for lines and polylines where z-indexes have to be 0'ed out
  283.         if(this.isConnector(node)){
  284.             var type=this.getConnectorType(node);
  285.             var subject=this.getShapeSubject(node);
  286.             if(type=='line'||type=='curve-line'){
  287.                 subject.style.zIndex=0;
  288.             }
  289.             else{
  290.                 //additional hack for polylines where paths have to be 0'ed out
  291.                 node.getElementsByTagName("polyline")[0].style.zIndex=0;
  292.                 node.getElementsByTagName("polyline")[0].points="0,0";
  293.             }
  294.         }
  295.         //we have to do this in the renderer since IE messes around with path, so we can fix them
  296.         this.container.appendChild(node);
  297.         //now restore the polyline path
  298.         if(this.isConnector(node)&&type=='ortho-line'){
  299.             var points=node.getAttribute("polyline-path");
  300.             node.getElementsByTagName("polyline")[0].points.value=points;
  301.         }
  302.     this.bringToFront(node);
  303.     return node;
  304. }
  305.  
  306.  
  307.  
  308. /**
  309. * a pure unadulterated hack because IE does not mantain correspondence between, 
  310. * polyline.points.value and polyline.points.item(x).value
  311. * so we basically save the value in an additional tag and use it when we have to do the paste or open
  312. **/
  313. VMLRenderer.prototype.savePolyLinePath=function(shape){
  314.     var polyline=shape.getElementsByTagName("polyline")[0];
  315.                 var path="";
  316.                 for (var i=0;i<polyline.points.length;i++){
  317.                     path+=polyline.points.item(i).value+",";
  318.                 
  319.                 }
  320.                 shape.setAttribute("polyline-path",path);
  321.  
  322. }
  323.  
  324. /**
  325. * this function is called to store the "correct" polyline paths before we refresh or save, see savePolylinePath for 
  326. * further explanation
  327. **/
  328. VMLRenderer.prototype.savePolyLinePaths=function(){
  329.     var nodes=this.getAllConnectors(this.container);
  330.     for (var i=0;i<nodes.length;i++){
  331.         if(nodes[i].getAttribute("type")=='ortho-line'){
  332.             this.savePolyLinePath(nodes[i]);
  333.         
  334.         }
  335.     }
  336.  
  337. }
  338.  
  339.  
  340.  
  341. /**
  342. *this method will return the actual subject of a shape, the subject could either be a path or line,polyline in case
  343. of connectors, this assumes that the shape has only one subject, if a shape is comples with multiple sub-shapes
  344. * see getAllSubshapes.
  345. **/
  346. VMLRenderer.prototype.getShapeSubject=function(shape){
  347.     if(!shape)return null;
  348.     if(this.isConnector(shape)){
  349.         var type=this.getConnectorType(shape);
  350.         if(type=='line')
  351.             return shape.getElementsByTagName('line')[0];
  352.         else if(type=='ortho-line')
  353.             return shape.getElementsByTagName('polyline')[0];
  354.         else
  355.             return shape.getElementsByTagName('curve')[0];
  356.     }
  357.     else{
  358.         var shapes=shape.getElementsByTagName("shape");
  359.         if(shapes.length>0){
  360.             return shapes[0];
  361.         }
  362.         //for backward compatibility only, these shapes are not used anymore!!!
  363.         else if(shape.getElementsByTagName("roundrect").length>0){
  364.             
  365.             var shapes=shape.getElementsByTagName("roundrect");
  366.             if(shapes.length>0){
  367.                 return shapes[0];
  368.             }
  369.         }
  370.         else if(shape.getElementsByTagName("rect").length>0){
  371.             
  372.             var shapes=shape.getElementsByTagName("rect");
  373.             if(shapes.length>0){
  374.                 return shapes[0];
  375.             }
  376.         }
  377.         else if(shape.getElementsByTagName("oval").length>0){
  378.             
  379.             var shapes=shape.getElementsByTagName("oval");
  380.             if(shapes.length>0){
  381.                 return shapes[0];
  382.             }
  383.         }
  384.     }
  385. }
  386. /**
  387.  * return all the subshapes for a given shape
  388.  * @param shape
  389.  * @return list of all subshapes
  390.  */
  391.  VMLRenderer.prototype.getAllSubShapes=function(shape){
  392.      if(!shape)return null;
  393.      return shape.getElementsByTagName("shape");
  394.  }
  395. /**************************************END SHAPE CREATION FUNCTIONS******************************/
  396. /**************************************BEGIN SHAPE ATTRIBUTE GETTERS AND SETTERS*****************/
  397. /**
  398. *return the type of this connector
  399. **/
  400. VMLRenderer.prototype.getConnectorType=function(shape){
  401.     return shape.getAttribute("type");
  402.  
  403.  
  404. }
  405.  
  406. /**
  407. *get from x for a valid connector
  408. **/
  409.  
  410. VMLRenderer.prototype.getConnectorFromX=function(shape){
  411.         var fromX=null;
  412.         var type=this.getConnectorType(shape);
  413.         if(type=='line'){
  414.             fromX=shape.getElementsByTagName("line")[0].from.x ;
  415.         }
  416.         else if (type=="ortho-line"){
  417.             var length=shape.getElementsByTagName("polyline")[0].points.length;
  418.             if(length==0){
  419.             
  420.                 return null;
  421.              }
  422.             fromX=shape.getElementsByTagName("polyline")[0].points.item(0).x ;
  423.         }
  424.         else if(type=="curve-line"){
  425.             fromX=this.getShapeSubject(shape).from.x;
  426.         }
  427.         return fromX;
  428.  
  429. }
  430. /**
  431. *get from y for a valid connector
  432. **/
  433. VMLRenderer.prototype.getConnectorFromY=function(shape){
  434.     var fromY=null;
  435.     var type=this.getConnectorType(shape);
  436.         if(type=='line'){
  437.             fromY=shape.getElementsByTagName("line")[0].from.y ;
  438.         }
  439.         else if (type=='ortho-line'){
  440.             var length=shape.getElementsByTagName("polyline")[0].points.length;
  441.             if(length==0){
  442.             
  443.                 return null;
  444.              }
  445.             fromY=shape.getElementsByTagName("polyline")[0].points.item(0).y ;
  446.         }
  447.         else if(type=="curve-line"){
  448.             fromY=this.getShapeSubject(shape).from.y;
  449.         }
  450.         return fromY;
  451.     
  452.  
  453. }
  454. /**
  455. *get to x for a valid connector
  456. **/
  457. VMLRenderer.prototype.getConnectorToX=function(shape){
  458.     var toX=null;
  459.     var type=this.getConnectorType(shape);
  460.         if(type=='line'){
  461.             toX=shape.getElementsByTagName("line")[0].to.x ;
  462.         }
  463.         else if (type=='ortho-line'){
  464.             var length=shape.getElementsByTagName("polyline")[0].points.length;
  465.             if(length==0){
  466.             
  467.                 return null;
  468.              }
  469.             toX=shape.getElementsByTagName("polyline")[0].points.item(length-1).x ;
  470.         }
  471.         else if(type=="curve-line"){
  472.             toX=this.getShapeSubject(shape).to.x;
  473.         }
  474.         return toX;
  475. }
  476. /**
  477. *get to y for a valid connector
  478. **/
  479.  
  480. VMLRenderer.prototype.getConnectorToY=function(shape){
  481.     var toY=null;
  482.     var type=this.getConnectorType(shape);
  483.         if(type=='line'){
  484.             toY=shape.getElementsByTagName("line")[0].to.y ;
  485.         }
  486.         else if (type=='ortho-line'){
  487.             var length=shape.getElementsByTagName("polyline")[0].points.length;
  488.             if(length==0){
  489.             
  490.                 return null;
  491.              }
  492.             toY=shape.getElementsByTagName("polyline")[0].points.item(length-1).y ;
  493.         }
  494.         else if(type=="curve-line"){
  495.             toY=this.getShapeSubject(shape).to.y;
  496.         }
  497.         return toY;
  498. }
  499.  
  500.  
  501. /**
  502. *set shape width
  503. **/
  504. VMLRenderer.prototype.setWidth=function(shape,width){
  505.     
  506.     if(shape)
  507.         shape.style.width=width+"px";
  508. }
  509. /**
  510. *set shape height
  511. **/
  512. VMLRenderer.prototype.setHeight=function(shape,height){
  513.     if(shape)
  514.         shape.style.height=height+"px";
  515. }
  516. /**
  517. *set shape x (left)
  518. **/
  519. VMLRenderer.prototype.setX=function(shape,left){
  520.     if(shape)
  521.         shape.style.left=left+"px";
  522. }
  523. /**
  524. *set shape Y(top)
  525. **/
  526. VMLRenderer.prototype.setY=function(shape,top){
  527.     if(shape)
  528.         shape.style.top=top+"px";
  529. }
  530. /**
  531. *set shape rotation
  532. **/
  533. VMLRenderer.prototype.setRotation=function(shape,rotation){
  534.     rotation=rotation%360;
  535.     shape.style.rotation=rotation;
  536.  
  537. }
  538. /**
  539. *get all shape objects (not including connectors)!
  540. **/
  541. VMLRenderer.prototype.getAllShapes=function(doc){
  542.     var nodes=doc.getElementsByTagName("group");
  543.     var array=$A(nodes);
  544.     return array;
  545. }
  546. /**
  547. *get all connectors (but not shapes)
  548. **/
  549. VMLRenderer.prototype.getAllConnectors=function(doc){
  550.     var nodes=doc.getElementsByTagName(this.CONNECTOR_TAG);
  551.     var array=$A(nodes);
  552.     return array;
  553. }
  554.  
  555.  
  556. /************************************END SHAPE ATTRIBUTE GETTERS AND SETTERS*********************************/
  557. /************************************BEGIN Z-INDEX FUNCTIONS************************************************/
  558. /**
  559. update the min and max z-index based on index provided by shape, used during open
  560. **/
  561. VMLRenderer.prototype.updateZIndex=function(shape){
  562.     if(!shape)return;
  563.     if(this.isConnector(shape)){
  564.         shape=this.getShapeSubject(shape);
  565.     }
  566.     
  567.     if(shape.style.zIndex<=this.minIndex){
  568.         this.minIndex=shape.style.zIndex;
  569.         this.minIndex--
  570.     }
  571.     if(shape.style.zIndex>=this.maxIndex){
  572.         this.maxIndex=shape.style.zIndex;
  573.         this.maxIndex++
  574.     }
  575.  
  576.  
  577. }
  578.  
  579. /**
  580. *send the shape to back
  581. *update for polyline
  582. **/
  583. VMLRenderer.prototype.sendToBack=function(shape){
  584.     if(!shape){
  585.         return;
  586.     }
  587.     else{
  588.         
  589.         this.setShapeZIndex(shape,this.minIndex--);
  590.     }
  591.  
  592. }
  593.  
  594. /**
  595. *bring the shape to front
  596. *
  597. **/
  598. VMLRenderer.prototype.bringToFront=function(shape){
  599.     if(!shape){
  600.         return;
  601.     }
  602.     else{
  603.         this.setShapeZIndex(shape,this.maxIndex++);
  604.     }
  605. }
  606. /**
  607.  * set the shape zindex and also bring the tracker to front or back, finally if 
  608.  * this shape is a connector, bring any text to the front/back
  609.  */
  610. VMLRenderer.prototype.setShapeZIndex=function(shape,index){
  611.     var actualShape=shape;
  612.     if(this.isConnector(shape)){
  613.         actualShape=this.getShapeSubject(shape);
  614.     }
  615.     
  616.     actualShape.style.zIndex=index;
  617.     var tracker = document.getElementById('tracker-group');
  618.     if(tracker)
  619.         tracker.style.zIndex=index;;
  620.     this.adjustConnectorTextZIndex(shape,index);
  621. }
  622. /**
  623.  * if a connector, adjust its text e.g bring it to front or back....
  624.  */
  625. VMLRenderer.prototype.adjustConnectorTextZIndex=function(shape,index){
  626.     //now check if this is a connector
  627.     
  628.     if(this.isConnector(shape)){
  629.         var text=shape.getElementsByTagName('line');
  630.         for(var i=0;i<text.length;i++){
  631.             text[i].style.zIndex=index;
  632.         }
  633.         var bgShape=shape.getElementsByTagName("rect");
  634.         if(bgShape.length>0){
  635.             bgShape[0].style.zIndex=index;
  636.         }
  637.     }
  638.     
  639.     
  640. }
  641. /**
  642. *remove the node in IE specfic manner
  643. **/
  644. VMLRenderer.prototype.remove = function(shape) {
  645.   if(shape)
  646.     shape.removeNode(true);
  647. }
  648.  
  649. VMLRenderer.prototype.setCursor=function(shape,cursor){
  650.     shape.style.cursor=cursor;
  651.  
  652. }
  653.  
  654. /**
  655. *move the shape, for line moves see moveLine
  656. **/
  657. VMLRenderer.prototype.move = function(shape, left, top) {
  658.     
  659.   if(!shape){
  660.     return;
  661.     }
  662.   if (shape.tagName == 'line') {
  663.     shape.style.marginLeft = left;
  664.     shape.style.marginTop = top;
  665.   }
  666.   else {
  667.     shape.style.left = left;
  668.     shape.style.top = top;
  669.   }
  670. };
  671. /**
  672. *respond to arrow keys for fine move
  673. **/
  674. VMLRenderer.prototype.fineMove = function(shape, move, isHorizontal) {
  675.   //todo fix for line!!!
  676.   if(!shape)return;
  677.   if (shape.tagName == 'line') {
  678.     shape.style.marginLeft = left;
  679.     shape.style.marginTop = top;
  680.   }
  681.   else {
  682.     if(isHorizontal){
  683.         var left=shape.style.left.split("px")[0];
  684.         left=(left*1)+move;
  685.         shape.style.left = left+"px";
  686.     
  687.     }
  688.     else{
  689.         var top=shape.style.top.split("px")[0];
  690.         top=(top*1)+move;
  691.         shape.style.top = top+"px";
  692.     }
  693.   }
  694. };
  695. VMLRenderer.prototype.fineRotateSelection=function(shape,angle){
  696.     var rotation=shape.style.rotation;
  697.         if(!rotation)
  698.             rotation=0;
  699.     var rotation=rotation+angle;
  700.     rotation=rotation%360;
  701.     if(rotation<0){
  702.         rotation=360+rotation;
  703.         
  704.     }
  705.     shape.style.rotation=rotation;
  706.     
  707. };
  708. VMLRenderer.prototype.rotate=function(shape,rotation){
  709.     if(!rotation){
  710.         rotation=0;
  711.     }
  712.     rotation=rotation%360;
  713.     if(rotation<0){
  714.         rotation=360+rotation;
  715.     }
  716.     shape.style.rotation=rotation;
  717.  
  718. }
  719. /**
  720. *set the opacity
  721. */
  722. VMLRenderer.prototype.setOpacity=function(shape,opacity){
  723.     //first check if this is a "complex" shape
  724.     var node=this.getShapeSubject(shape);
  725.     this.setFillAttribute(node,"opacity",opacity);
  726.  
  727. }
  728. /**
  729. *get the opacity
  730. **/
  731. VMLRenderer.prototype.getOpacity=function(shape){
  732.     var node=this.getShapeSubject(shape);
  733.     if(node){
  734.         var opacity=this.getFillAttribute(node,"opacity");
  735.         opacity=(opacity==null)?1.0:Math.round(opacity*10);
  736.         opacity=(opacity/10).toFixed(1);
  737.         return opacity;
  738.     }
  739.     else{
  740.         return null
  741.     }
  742.  
  743. }
  744.  
  745. /**
  746. *get the gradient
  747. **/
  748. VMLRenderer.prototype.getGradient=function(shape){
  749.     var node=this.getShapeSubject(shape);
  750.     if(node){
  751.         var gradient=this.getFillAttribute(node,"type");
  752.         gradient=(gradient==null)?"solid":gradient;
  753.         return gradient;
  754.     }
  755.     else{
  756.         return null;
  757.     }
  758.  
  759. }
  760. /**
  761. *setFillcolor
  762. **/
  763. VMLRenderer.prototype.setFillColor=function(shape,fillColor){
  764.     //debugger;
  765.     //first check if this is a "complex" shape
  766.     var groups=shape.getElementsByTagName("v:group");
  767.     if(groups.length==0){
  768.         //this is a simple shape, so we will set its fill
  769.             var atts=new Array("fillcolor");
  770.             var vals=new Array(fillColor);
  771.             
  772.             this.setShapeAttributes(shape,atts,vals);
  773.         }
  774.         
  775.     
  776.     else{
  777.         for(var i=0;i<groups.length;i++){
  778.             this.setFillColor(groups[i],fillColor);
  779.         }
  780.     }
  781.  
  782. }
  783.  
  784. /**
  785. *get the fill color
  786. *@param shape
  787. **/
  788. VMLRenderer.prototype.getFillColor=function(shape){
  789.     var node=this.getShapeSubject(shape);
  790.     if(node){
  791.         var fillColor=node.getAttribute("fillcolor");
  792.         if(fillColor) return fillColor.value;
  793.         else return "#ffffff";
  794.     }
  795.     else{
  796.         return "#ffffff";
  797.     }
  798. }
  799.  
  800. /**
  801. *get the line color
  802. *@param shape
  803. **/
  804. VMLRenderer.prototype.getLineColor=function(shape){
  805.     var node=this.getShapeSubject(shape);
  806.     if(node){
  807.         var strokeColor=node.getAttribute("strokecolor");
  808.         if(strokeColor) return strokeColor.value;
  809.         else return "#ffffff";
  810.     }
  811.     else{
  812.         return "#ffffff";
  813.     }
  814. }
  815.  
  816. /**
  817.  * get the line dash style
  818.  * @return one of -"solid", "short-dash","long-dash"
  819.  */
  820. VMLRenderer.prototype.getLineDashStyle=function(shape){
  821.      var subject=this.getShapeSubject(shape);
  822.      var stroke=subject.getElementsByTagName("stroke");
  823.      if(stroke.length==0)return 'solid';
  824.      var dashStyle=stroke[0].getAttribute("dashstyle");
  825.      if(!dashStyle||dashStyle.value==""||dashStyle.value==this.SOLID_DASH)
  826.          return 'solid';
  827.      else if(dashStyle.value.toLowerCase()==this.LONG_DASH)
  828.          return "long-dash";
  829.      else 
  830.          return "short-dash";
  831.  }
  832.  
  833.  /**
  834.   * set the line dash style, we will set this on all 
  835.   */
  836. VMLRenderer.prototype.setLineDashStyle=function(shape,style){
  837.     if(style=="long-dash")style=this.LONG_DASH;
  838.     else if(style=="short-dash")style=this.SHORT_DASH;
  839.     else style=this.SOLID_DASH;
  840.     if(this.isConnector(shape)){
  841.         var subject=this.getShapeSubject(shape);
  842.         var stroke=subject.getElementsByTagName("stroke");
  843.         stroke[0].setAttribute("dashstyle",style)
  844.     }
  845.     else{
  846.         var subShapes=this.getAllSubShapes(shape)
  847.         for(var i=0;i<subShapes.length;i++){
  848.             
  849.             var stroke=subShapes[i].getElementsByTagName("stroke");
  850.             if(!stroke||stroke.length==0){
  851.                 stroke=this.createElement("stroke",this.VML_SVG_NAMESPACE);
  852.                 subShapes[i].appendChild(stroke);
  853.             }
  854.             else{
  855.                 stroke=stroke[0];
  856.             }
  857.             stroke.setAttribute("dashstyle",style)
  858.         }
  859.     }
  860. }
  861.  
  862.  
  863.  
  864.  
  865. /**
  866. *get the stroke width of the shape
  867. *@param shape
  868. **/
  869. VMLRenderer.prototype.getStrokeWidth=function(shape){
  870.     var node=this.getShapeSubject(shape);
  871.     if(node.getAttribute("strokeweight")!="undefined")
  872.         return (parseFloat(node.strokeweight) * (screen.logicalXDPI / 72)) + 'px';
  873.     else
  874.         return 0;
  875. }   
  876. /**
  877. *set the stroke width of the shape
  878. *@param shape
  879. **/
  880. VMLRenderer.prototype.setStrokeWidth=function(shape,value){
  881.     if (value != '0px') {
  882.       shape.strokeweight = parseInt(value) + 'px';
  883.       attList=new Array("stroked","strokeweight");
  884.       attValues=new Array("true",parseInt(value)+'px');
  885.       this.setShapeAttributes(shape,attList,attValues);
  886.        }
  887.      else{
  888.       shape.stroked = 'false';
  889.       shape.strokeweight = 0 + 'px';
  890.       attList=new Array("stroked","strokeweight");
  891.       attValues=new Array("false",0+'px');
  892.       this.setShapeAttributes(shape,attList,attValues);
  893.      
  894.      }
  895.  
  896.  
  897. }
  898. /**
  899. *set gradient
  900. *@param shape
  901. **/
  902. VMLRenderer.prototype.setGradient=function(shape,gradient){
  903.         var node=this.getShapeSubject(shape);
  904.         this.setFillAttribute(node,"type",gradient);
  905. }
  906.  
  907. /**
  908. *set the shape shadow
  909. *@param shape
  910. *@param shape value
  911. **/
  912. VMLRenderer.prototype.setShadow=function(shape,value){
  913.     //first check if this is a "complex" shape
  914.     var node=this.getShapeSubject(shape);
  915.     
  916.     var shadowArray=node.getElementsByTagName("shadow");
  917.     var shadow=null;
  918.     if(!shadowArray||shadowArray.length==0){
  919.         shadow=this.container.ownerDocument.createElement("v:shadow");
  920.         node.appendChild(shadow);
  921.     }
  922.     else{
  923.         shadow=shadowArray[0];
  924.     }
  925.     shadow.on=value;
  926. }
  927. /**
  928. *get shadow
  929. *@param shape
  930. **/
  931. VMLRenderer.prototype.getShadow=function(shape){
  932.     var node=this.getShapeSubject(shape);
  933.     var shadowArray=node.getElementsByTagName("shadow");
  934.     
  935.     if(!shadowArray||shadowArray.length==0){
  936.         return false;
  937.     }
  938.     return shadowArray[0].on;
  939. }
  940.  
  941. /**
  942. *set a value in the fill attribute
  943. *@param node to set value in
  944. *@param attribute name to be set e.g opacity
  945. *@param value to be set
  946. **/
  947. VMLRenderer.prototype.setFillAttribute=function (node,att,value){
  948.     //debugger;
  949.     var fillArray=node.getElementsByTagName("fill");
  950.     var fill=null;
  951.     if(!fillArray||fillArray.length==0){
  952.         fill=this.container.ownerDocument.createElement("v:fill");
  953.         node.appendChild(fill);
  954.     }
  955.     else{
  956.         fill=fillArray[0];
  957.     }
  958.     var gradient=fill.type;
  959.     if(!gradient){
  960.         gradient="solid";
  961.     }
  962.     var atts=new Array("type",att);
  963.     var attValues=new Array(gradient,value);
  964.     setAttributes(fill,atts,attValues);
  965.     
  966. }
  967. /**
  968. * get a value in the fill attribute
  969. **/
  970. VMLRenderer.prototype.getFillAttribute=function(node,att){
  971.     var fillArray=node.getElementsByTagName("fill");
  972.     var fill=null;
  973.     if(!fillArray||fillArray.length==0){
  974.         return null;
  975.     }
  976.     else{
  977.         return fillArray[0].getAttribute(att);
  978.     }
  979. }
  980.  
  981.  
  982.  
  983.  
  984.  
  985. /**
  986. *resize shape
  987. **/
  988. VMLRenderer.prototype.resize = function(shape, fromX, fromY, toX, toY) {
  989.   
  990.   var deltaX = toX - fromX;
  991.   var deltaY = toY - fromY;
  992.  
  993.  
  994.   if (this.isConnector(shape)) {
  995.   var type=this.getConnectorType(shape);
  996.     if(type=='line'){
  997.     
  998.         var vml=shape.getElementsByTagName("line")[0];
  999.         vml.setAttribute('to', toX + 'px,' + toY + 'px');
  1000.     }
  1001.     else if(type=='ortho-line'){
  1002.         this.drawOrthoLine(shape,fromX,fromY,toX,toY);
  1003.     }
  1004.     else if(type=='curve-line'){//this is a curve
  1005.         this.drawCurveLine(shape,fromX,fromY,toX,toY,false);
  1006.     }
  1007.   }
  1008.   else {
  1009.     if (deltaX < 0) {
  1010.       shape.style.left = toX + 'px';
  1011.       shape.style.width = -deltaX + 'px';
  1012.     }
  1013.     else {
  1014.       var width=0;
  1015.       var newWidth=(width*1)+deltaX;
  1016.       shape.style.width = (newWidth) + 'px';
  1017.     }
  1018.   
  1019.     if (deltaY < 0) {
  1020.       shape.style.top = toY + 'px';
  1021.       shape.style.height = -deltaY + 'px';
  1022.     }
  1023.     else {
  1024.       var height=0;
  1025.       var newHeight=(height*1)+deltaY;
  1026.       shape.style.height = newHeight + 'px';
  1027.     }
  1028.   }
  1029.   
  1030. };
  1031.  
  1032.  
  1033.  
  1034. //a utility function to set attributes for all the child shapes within a group
  1035. //however we want to ignore all text elements
  1036. VMLRenderer.prototype.setShapeAttributes=function(group,attList,attValues){
  1037.     
  1038.     var shape=this.getShapeSubject(group);
  1039.     if(shape)
  1040.         setAttributes(shape,attList,attValues);
  1041.   
  1042. }
  1043. /**a utility function to set attributes on an element
  1044. attlist and attvalues should have the same number of elements
  1045. **/
  1046. function setAttributes(element,attList,attValues){
  1047.     for(var i=0;i<attList.length;i++){
  1048.         element.setAttribute(attList[i],attValues[i]);
  1049.     }
  1050. }
  1051. /**
  1052. *determine the appropriate handler for the command and respond. 
  1053. *Zoom is provided to set up the correct sizing for font/lines etc
  1054. **/
  1055. VMLRenderer.prototype.editCommand = function(shape, cmd, value,zoom)
  1056. {
  1057.   
  1058.   if (shape != null) {
  1059.     if(cmd=='sendBack'){
  1060.         this.sendToBack(shape);
  1061.     }
  1062.     else if(cmd=='bringFront'){
  1063.         this.bringToFront(shape);
  1064.     }
  1065.     else if(cmd=='opacity'){
  1066.         this.setOpacity(shape,value);
  1067.     }
  1068.     else if(cmd=='gradient'){
  1069.         this.setGradient(shape,value);
  1070.     }
  1071.     else if(cmd=='shadow'){
  1072.         this.setShadow(shape,value);
  1073.     }
  1074.     else if(cmd=='linestyle'){
  1075.         this.setLineStyle(shape,value);
  1076.     }
  1077.     else if (cmd == 'fillcolor') {
  1078.       if(this.isConnector(shape)){
  1079.           return;
  1080.       }
  1081.       else if (value != '') {
  1082.         shape.filled = 'true';
  1083.         shape.fillcolor.value=value;
  1084.         shape.fillcolor=value;
  1085.         attList=new Array("filled","fillcolor");
  1086.         attValues=new Array("true",value);
  1087.         this.setShapeAttributes(shape,attList,attValues);
  1088.       }
  1089.       else {
  1090.         shape.filled = 'false';
  1091.        shape.setAttribute("fillcolor",value);
  1092.         attList=new Array("filled","fillcolor");
  1093.         attValues=new Array("true",value);
  1094.         this.setShapeAttributes(shape,attList,attValues);
  1095.        
  1096.       }
  1097.     }
  1098.     else if (cmd == 'linecolor') {
  1099.       if (value != '') {
  1100.         shape.stroked = 'true';
  1101.         shape.strokecolor = value;
  1102.         attList=new Array("stroked","strokecolor");
  1103.         attValues=new Array("true",value);
  1104.         this.setShapeAttributes(shape,attList,attValues);
  1105.       }
  1106.       else {
  1107.         shape.stroked = 'false';
  1108.         shape.strokecolor = '';
  1109.         attList=new Array("stroked","strokecolor");
  1110.         attValues=new Array("false",'');
  1111.         this.setShapeAttributes(shape,attList,attValues);
  1112.       }
  1113.     }
  1114.     else if (cmd == 'linewidth') {
  1115.      this.setStrokeWidth(shape,value);
  1116.     }
  1117.     else if (cmd=='linedashstyle'){
  1118.         this.setLineDashStyle(shape,value);
  1119.     }
  1120.      else if(cmd=='fontSize'||cmd=='fontFamily'||cmd=='bold'||cmd=='italic'||cmd=='fontColor'||cmd=='align'){
  1121.         
  1122.         var font=new Object();
  1123.         font.size='';
  1124.         font.family='';
  1125.         font.color='';
  1126.         font.align='';
  1127.         font.italics='';
  1128.         font.bold='';
  1129.         if(cmd=='fontSize'){
  1130.             font.size=value;
  1131.             this.setFont(shape,font,zoom);
  1132.         }
  1133.         else if(cmd=='fontFamily'){
  1134.             font.family=value;
  1135.             this.setFont(shape,font,zoom);
  1136.         }
  1137.         else if(cmd=='bold'){
  1138.             var oldFont=this.getFont(shape);
  1139.             
  1140.             if(oldFont.bold=='bold'){
  1141.                 font.bold='normal';
  1142.             }
  1143.             else{
  1144.                 font.bold='bold';
  1145.             }
  1146.             this.setFont(shape,font);
  1147.         }
  1148.    
  1149.         else if(cmd=='italic'){
  1150.             //debugger;
  1151.             var oldFont=this.getFont(shape);
  1152.             if(oldFont.italics=='italic'){
  1153.                 font.italics='normal';
  1154.             }
  1155.             else{
  1156.                 font.italics='italic';
  1157.             }
  1158.             this.setFont(shape,font);
  1159.         }
  1160.         else if(cmd=='fontColor'){
  1161.             font.color=value;
  1162.             this.setFont(shape,font);
  1163.         }
  1164.         else if(cmd=='align'){
  1165.             font.align=value;
  1166.             this.setFont(shape,font);
  1167.         }
  1168.     
  1169.     }
  1170.   }
  1171.    
  1172. }
  1173.  
  1174.  
  1175. VMLRenderer.prototype.queryCommand = function(shape, cmd)
  1176. {
  1177.   if (shape != null) {
  1178.     if (cmd == 'fillcolor') {
  1179.         return this.getFillColor(shape);
  1180.     }
  1181.     else if (cmd == 'linecolor') {
  1182.           return this.getLineColor(shape);
  1183.     }
  1184.     else if (cmd == 'linewidth') {
  1185.       if (shape.stroked == 'false') {
  1186.         return '';
  1187.       }
  1188.       else {
  1189.         // VML always transforms the pixels to points, so we have to convert them back
  1190.         return parseInt(this.getStrokeWidth(shape)) + 'px';
  1191.       }
  1192.     }
  1193.      else if(cmd=='font'){
  1194.         
  1195.         return this.getFont(shape);
  1196.     }
  1197.     else if(cmd=='linestyle'){
  1198.         return this.getLineStyle(shape);
  1199.     }
  1200.     else if(cmd=='opacity'){
  1201.         return this.getOpacity(shape);
  1202.     }
  1203.     else if(cmd=="gradient"){
  1204.         return this.getGradient(shape);
  1205.     }
  1206.     else if(cmd=="shadow"){
  1207.         return ""+this.getShadow(shape);
  1208.     }
  1209.      else if (cmd=='linedashstyle'){
  1210.         return this.getLineDashStyle(shape);
  1211.     }
  1212.    
  1213.   }
  1214. }
  1215. /**
  1216. *create a handle shape, experimental, not used right now.
  1217. **/
  1218. VMLRenderer.prototype.getHandles=function(shape){
  1219.     var handles=new Array();
  1220.     if(!shape){
  1221.         return handles;
  1222.     }
  1223.     var nodes=shape.getElementsByTagName("h");
  1224.     if(nodes.length==0){
  1225.         return handles;
  1226.     }
  1227.     //now get all the adjustments
  1228.     var shapeNode=shape.getElementsByTagName("shape");
  1229.     //if we have handles we must have adjustments
  1230.     var adjLength=shapeNode[0].adj.length;
  1231.     var adjs=new Array();
  1232.     for(var i=0;i<adjLength;i++){
  1233.         adjs[i]=shapeNode[0].adj.item(i);
  1234.     
  1235.     }
  1236.     //now lets create the handles
  1237.     for(var i=0;i<nodes.length;i++){
  1238.         var handle=this.container.ownerDocument.createElement("v:rect");
  1239.         handle.coordsize="21600,21600";
  1240.         handle.style.position="absolute";
  1241.         handle.id="resize-right";
  1242.         handle.style.width=30;
  1243.         handle.style.position="absolute";
  1244.         handle.style.height=30;
  1245.         handle.setAttribute('filled', 'true');
  1246.         handle.setAttribute('fillcolor', 'yellow');
  1247.         var positionX=nodes[i].position.split(",")[0];
  1248.         var positionY=nodes[i].position.split(",")[1];
  1249.         if(positionX.indexOf("#")==0){
  1250.             positionX=positionX.split("#")[1]*1;
  1251.             handle.style.left=adjs[positionX]-20;
  1252.         }
  1253.         if(positionY.indexOf("#")==0){
  1254.             positionY=positionY.split("#")[1];
  1255.             handle.style.top=adjs[positionY]-20;
  1256.             
  1257.         }
  1258.         handles[handles.length]=handle;
  1259.     
  1260.     }
  1261.     return handles;
  1262.  
  1263.  
  1264. }
  1265. /**********************************begin line functions*******************/
  1266.  
  1267. /**
  1268.  * move the "to" or "from" part of the line segment
  1269.  */
  1270. VMLRenderer.prototype.moveLine=function(shape,toX,toY, isFrom){
  1271.     if(!this.isConnector(shape)){
  1272.         return;
  1273.     }
  1274.     var type=this.getConnectorType(shape);
  1275.     var vml=this.getShapeSubject(shape);
  1276.     if(type=='line'||type=='curve-line'){
  1277.         
  1278.         if(isFrom){
  1279.             vml.setAttribute('from', toX + 'px,' + toY + 'px');
  1280.             vml.from.x=toX/this.screenXDPI;
  1281.             vml.from.y=toY/this.screenXDPI;
  1282.         }
  1283.         else{
  1284.             vml.setAttribute('to', toX + 'px,' + toY + 'px');
  1285.             vml.to.x=toX/this.screenXDPI;
  1286.             vml.to.y=toY/this.screenXDPI;
  1287.         }
  1288.     }
  1289.     else{
  1290.         if(isFrom){
  1291.             //debugger;
  1292.             var length=vml.points.length;
  1293.             var x=vml.points.item(length-1).x*this.screenXDPI;
  1294.             var y=vml.points.item(length-1).y*this.screenXDPI
  1295.             this.drawOrthoLine(shape,toX,toY,x,y);
  1296.         }
  1297.         else{
  1298.             var x=vml.points.item(0).x*this.screenXDPI;
  1299.             var y=vml.points.item(0).y*this.screenXDPI;
  1300.             this.drawOrthoLine(shape,x,y,toX,toY);
  1301.         }
  1302.     }
  1303.         
  1304. }
  1305. /**
  1306. * the only difference between this method and move line is that this method converts pixels to points for polylines before 
  1307. *setting them
  1308. **/
  1309. VMLRenderer.prototype.moveLinePoint=function(shape,toX,toY, isFrom){
  1310.     if(!this.isConnector(shape)){
  1311.         return;
  1312.     }
  1313.     var type=this.getConnectorType(shape);
  1314.     var vml=this.getShapeSubject(shape);
  1315.     if(type=='line'||type=='curve-line'){
  1316.         if(isFrom){
  1317.             vml.setAttribute('from', toX + 'pt,' + toY+'pt');
  1318.             vml.from.x=toX;
  1319.             vml.from.y=toY;
  1320.         }
  1321.         else{
  1322.             vml.setAttribute('to', toX + 'pt,' + toY+'pt' );
  1323.             vml.to.x=toX;
  1324.             vml.to.y=toY;
  1325.         }
  1326.     }
  1327.     else{
  1328.         toX=toX*this.screenXDPI;
  1329.         toY=toY*this.screenXDPI;
  1330.         if(isFrom){
  1331.             //debugger;
  1332.             var length=vml.points.length;
  1333.             var x=vml.points.item(length-1).x*this.screenXDPI;
  1334.             var y=vml.points.item(length-1).y*this.screenXDPI;
  1335.             this.drawOrthoLine(shape,toX,toY,x,y);
  1336.         }
  1337.         else{
  1338.             var x=vml.points.item(0).x*this.screenXDPI;
  1339.             var y=vml.points.item(0).y*this.screenXDPI;
  1340.             this.drawOrthoLine(shape,x,y,toX,toY);
  1341.         }
  1342.     }
  1343.  
  1344. }
  1345.  
  1346. /*******************************************BEGIN CURVE CONNECTOR FUNCTIONS***********************************/
  1347. VMLRenderer.prototype.drawCurveLine=function(shape,fromX,fromY,toX,toY,resize){
  1348.     var subject=this.getShapeSubject(shape);
  1349.     subject.from=fromX+","+fromY;
  1350.     subject.from.x=fromX/this.screenXDPI;
  1351.     subject.from.y=fromY/this.screenXDPI;
  1352.     subject.to=toX+","+toY;
  1353.     subject.to.x=toX/this.screenXDPI;
  1354.     subject.to.y=toY/this.screenXDPI;
  1355.     if(!resize){
  1356.         var x1=Math.abs(fromX-toX);
  1357.         var y1=Math.abs(fromY-toY);
  1358.         var cx1=(fromX<toX)?(fromX*1)+(x1*(1/4)):(fromX*1)-(x1*(1/4));
  1359.         var cx2=(fromX<toX)?(toX*1)-(x1*(1/4)):(toX*1)+(x1*(1/4));
  1360.         var cy1=(fromY<toY)?(fromY*1)+(y1*(1/4)):(fromY*1)-(y1*(1/4));
  1361.         var cy2=(fromY<toY)?(toY*1)-(y1*(1/4)):(toY*1)+(y1*(1/4));
  1362.         this.setControl1(shape,cx1,cy1);
  1363.         this.setControl2(shape,cx2,cy2);
  1364.     }
  1365.     
  1366. /********************************************END CURVE CONNECTOR FUNCTIONS*************************************/
  1367.  
  1368. /********************************************BEGIN GENERAL LINE FUNCTIONS***************************************/
  1369.  
  1370. }
  1371. /**
  1372. *get the location of control point 1
  1373. **/
  1374. VMLRenderer.prototype.getControl1=function(shape){
  1375.     var subject=this.getShapeSubject(shape);
  1376.     var obj=new Object();
  1377.     obj.x=subject.control1.x*this.screenXDPI;
  1378.     obj.y=subject.control1.y*this.screenXDPI;
  1379.     return obj;
  1380.  
  1381. }
  1382. /**
  1383. *set the new location of control point 1
  1384. **/
  1385. VMLRenderer.prototype.setControl1=function(shape,cx1,cy1){
  1386.     var subject=this.getShapeSubject(shape);
  1387.     subject.control1=cx1+","+cy1;
  1388.     subject.control1.x=cx1/this.screenXDPI;
  1389.     subject.control1.y=cy1/this.screenXDPI;
  1390. }
  1391.  
  1392. /**
  1393. *get the location of control point 1
  1394. **/
  1395. VMLRenderer.prototype.getControl2=function(shape){
  1396.     var subject=this.getShapeSubject(shape);
  1397.     var obj=new Object();
  1398.     obj.x=subject.control2.x*this.screenXDPI;
  1399.     obj.y=subject.control2.y*this.screenXDPI;
  1400.     return obj;
  1401.  
  1402. }
  1403.  
  1404. /**
  1405. *set the new location for control point 2
  1406. **/
  1407. VMLRenderer.prototype.setControl2=function(shape,cx1,cy1){
  1408.     var subject=this.getShapeSubject(shape);
  1409.     subject.control2=cx1+","+cy1;
  1410.     subject.control2.x=cx1/this.screenXDPI;
  1411.     subject.control2.y=cy1/this.screenXDPI;
  1412.  
  1413.  
  1414. }
  1415. /*******************************************BEGIN ORTHOGONAL CONNECTOR FUNCTIONS******************************/
  1416. /**
  1417.  * get the segments of the orthogonal connector--get the central segment, 
  1418.  * @return {object} containing x,y,x2,y2
  1419.  */
  1420. VMLRenderer.prototype.getOrthoLineCenterSegment=function(shape){
  1421.     //debugger;
  1422.     var obj=new Object();
  1423.     var points=this.getShapeSubject(shape).points;
  1424.     
  1425.     //get the center point
  1426.     var centerPoint=Math.round(points.length/2)-1;
  1427.     var center=points.item(centerPoint);
  1428.     var before=points.item(centerPoint-1);
  1429.     var after=points.item(centerPoint+1);
  1430.     var distanceA=((center.y-before.y)*(center.y-before.y))+((center.x-before.x)*(center.x-before.x));
  1431.     var distanceB=((center.y-after.y)*(center.y-after.y))+((center.x-after.x)*(center.x-after.x));
  1432.     var referencePoint=distanceA>distanceB?before:after;
  1433.     if(distanceA>distanceB){
  1434.         obj.x=this.pointToPixel(referencePoint.x);
  1435.         obj.y=this.pointToPixel(referencePoint.y);
  1436.         obj.x2=this.pointToPixel(center.x);
  1437.         obj.y2=this.pointToPixel(center.y);
  1438.     }
  1439.     else{
  1440.         obj.x2=this.pointToPixel(referencePoint.x);
  1441.         obj.y2=this.pointToPixel(referencePoint.y);
  1442.         obj.x=this.pointToPixel(center.x);
  1443.         obj.y=this.pointToPixel(center.y);
  1444.     }
  1445.     return obj;
  1446. }
  1447. /*
  1448. *special method to draw orthogonal lines. first calculate the horizontal distance, then calculate the vertical distance, 
  1449. * if horizontal> vertical, split horizontal in 1/2 and vice versa, set this in the shape
  1450. */
  1451. VMLRenderer.prototype.drawOrthoLine= function(shape,fromX,fromY,toX,toY,resize){
  1452.     
  1453.     var path=this.calculateOrthoLinePath(shape,fromX,fromY,toX,toY);
  1454.     this.getShapeSubject(shape).points.value=path;
  1455. }
  1456.  
  1457.  
  1458. /*********************************************END ORTHOLINE FUNCTIONS*******************************/
  1459. /**
  1460. * get the current line style (arrow head style)
  1461. **/
  1462. VMLRenderer.prototype.getLineStyle=function(connector){
  1463.     if(!this.isConnector(connector))return '';
  1464.     var type=this.getConnectorType(connector);
  1465.     var line=this.getShapeSubject(connector);
  1466.     var stroke=line.getElementsByTagName('stroke')[0];
  1467.     if(stroke.startarrow=='classic'&&stroke.endArrow=='classic'){
  1468.         return 'arrow-both'
  1469.     }
  1470.     else if(stroke.startarrow=='classic'){
  1471.         return 'arrow-from'
  1472.     }
  1473.     if(stroke.endArrow=='classic'){
  1474.         return 'arrow-to'
  1475.     }
  1476.     else{
  1477.         return 'none';
  1478.     }
  1479.  
  1480. }
  1481. /**
  1482. * set the current line style (arrow head style)
  1483. **/
  1484. VMLRenderer.prototype.setLineStyle=function(connector,style){
  1485.     if(!this.isConnector(connector))return;
  1486.     var line=this.getShapeSubject(connector);
  1487.     var stroke=line.getElementsByTagName('stroke')[0];
  1488.     if(style=='arrow-from'||style=='arrow-both'){
  1489.         
  1490.         stroke.startarrow='classic';
  1491.     }
  1492.     else{
  1493.         stroke.startarrow='none';
  1494.     }
  1495.     
  1496.     if(style=='arrow-to'||style=='arrow-both'){
  1497.         
  1498.         stroke.endarrow='classic';
  1499.     }
  1500.     else{
  1501.         stroke.endarrow='none';
  1502.     }
  1503.     
  1504. }
  1505.  
  1506. /**
  1507. * show the connection points for a shape
  1508. **/
  1509. VMLRenderer.prototype.showConnectionPoints=function(shape){
  1510.     if(!shape)return;
  1511.     //debugger;
  1512.     var rect=this.bounds(shape);
  1513.     var rotation=rect['rotation'];
  1514.     if(!rotation)rotation=0;
  1515.     this.remove($('active-shape-tracker'));
  1516.     var doc=this.container.ownerDocument;
  1517.     var group=doc.createElement("v:group");
  1518.     group.style.left=shape.style.left;
  1519.     group.style.top=shape.style.top;
  1520.     group.style.width=shape.style.width;
  1521.     group.style.height=shape.style.height;
  1522.     group.style.position="ABSOLUTE";
  1523.     group.style.rotation=rotation;
  1524.     group.style.zIndex=(shape.style.zIndex*1)+1;
  1525.     group.id='active-shape-tracker';
  1526.     var width=10*(1000/(rect["width"]+50));
  1527.     var height=10*(1000/(rect["height"]+50));
  1528.     var nodeList=shape.getElementsByTagName("connection-point");
  1529.     for(var i=0;i<nodeList.length;i++){
  1530.         var node=nodeList.item(i);
  1531.         var oval=doc.createElement("v:oval");
  1532.         
  1533.         oval.filled="t";
  1534.         oval.fillcolor="red";
  1535.         oval.style.width="10px";
  1536.         oval.style.height="10px";
  1537.         oval.style.position="ABSOLUTE";
  1538.         
  1539.         
  1540.         oval.style.width=width;
  1541.         oval.style.height=height;
  1542.         oval.style.left=(node.x-(width/2))+"px";
  1543.         oval.style.top=(node.y-(height/2))+"px";
  1544.         
  1545.         oval.coordsize="21600,21600";
  1546.         group.appendChild(oval);
  1547.         
  1548.     
  1549.     }
  1550.     this.container.appendChild(group);
  1551. }
  1552. /**
  1553. *create a namespaced element
  1554. **/
  1555. VMLRenderer.prototype.createElement=function(elementTag,namespaceURI){
  1556.     var element=null;
  1557.     if(namespaceURI==this.VML_SVG_NAMESPACE)
  1558.         elementTag="v:"+elementTag;
  1559.     element= this.container.ownerDocument.createElement(elementTag);
  1560.     if(namespaceURI=='CUMULATE_LABS'){
  1561.         element.setAttribute("xmlns:c","urn:schemas-cumulatelabs-com:vml");
  1562.     }
  1563.     return element;
  1564. }
  1565.  
  1566. /*
  1567. *connectLine, first calculate if the line end matches a connection point
  1568. * if yes then add an entry to ensure that line and shape are connected
  1569. **/
  1570. VMLRenderer.prototype.connectLine=function(shape,connector,toOrFrom){
  1571.     
  1572.     if(!connector)return;
  1573.     //first disconnect the line
  1574.     this.disconnectLineFromShape(connector,toOrFrom);
  1575.     if(!shape)return;
  1576.     //get the line coordinates in pixels
  1577.     var screenxdpi=screen.logicalXDPI / 72;
  1578.     var x=0;
  1579.     var y=0;
  1580.     var line=this.getShapeSubject(connector);
  1581.     var type=this.getConnectorType(connector);
  1582.     if(type=='line'||type=='curve-line'){
  1583.         x=line.getAttribute(toOrFrom).x*this.screenXDPI;
  1584.         y=line.getAttribute(toOrFrom).y*this.screenXDPI;
  1585.     }
  1586.     else{
  1587.         if(toOrFrom=="from"){
  1588.             x=line.points.item(0).x*this.screenXDPI;
  1589.             y=line.points.item(0).y*this.screenXDPI;
  1590.         
  1591.         }
  1592.         else{
  1593.             var length=connector.getElementsByTagName("polyline")[0].points.length;
  1594.             if(length==0)return;
  1595.             x=line.points.item(length-1).x*this.screenXDPI;
  1596.             y=line.points.item(length-1).y*this.screenXDPI;
  1597.         }
  1598.     
  1599.     }
  1600.     //now get the shape center
  1601.     var left=shape.style.left.split('px')[0];
  1602.     var top=shape.style.top.split('px')[0];
  1603.     var width=shape.style.width.split('px')[0];
  1604.     var height=shape.style.height.split('px')[0];
  1605.     var centerX=(left*1)+(width/2);
  1606.     var centerY=(top*1)+(height/2);
  1607.     //get the rotation
  1608.     var rotation=shape.style.rotation;
  1609.     if(!rotation)rotation=0;
  1610.     //get the shape coordinate size, hardcode for now
  1611.     coordX=1000;
  1612.     coordY=1000;
  1613.     
  1614.     var connectionList=shape.getElementsByTagName("connection-point");
  1615.     for(var i=0;i<connectionList.length;i++){
  1616.         var node=connectionList.item(i);
  1617.         //for each connection point get its(unrotated) pixel location
  1618.         var conX=(left*1)+((node.x/coordX)*width);
  1619.         var conY=(top*1)+((node.y/coordY)*height);
  1620.         //now translate the center to the origin
  1621.         conX=conX-centerX;
  1622.         conY=conY-centerY;
  1623.         //now rotate and translate back
  1624.         finalX=((conX*Math.cos((Math.PI/180)*(rotation)))-(conY*Math.sin((Math.PI/180)*(rotation)))*1)+(centerX*1);
  1625.         finalY=((conX*Math.sin((Math.PI/180)*(rotation)))+(conY*Math.cos((Math.PI/180)*(rotation)))*1)+(centerY*1);
  1626.         
  1627.         if(x>(finalX-4)&&x<((finalX*1)+4)&&y>(finalY-4)&&y<((finalY*1)+4)){
  1628.             this.connectLineToShape(shape,connector,toOrFrom,node,i);
  1629.             var isFrom=(toOrFrom=="from")?true:false;
  1630.             this.moveLineWithShape(shape);
  1631.             $('help').innerHTML="Connected line to shape";
  1632.             //no need to go on, we found our connection point
  1633.             return;
  1634.         }
  1635.     
  1636.     }
  1637. }
  1638.  
  1639. /**
  1640. *show the line tracker
  1641. **/
  1642. VMLRenderer.prototype.showLineTracker=function(shape){
  1643.     //debugger;
  1644.     var doc=this.container.ownerDocument;
  1645.     var vml=null;
  1646.     var load=this.loadShape("tracker","c:line-tracker");
  1647.     var dummy = doc.createElement("div");
  1648.     dummy.insertAdjacentHTML("AfterBegin", load.xml);
  1649.     var parent = dummy.firstChild;
  1650.     parent.id="tracker-group";
  1651.     this.updateLineTracker(shape,parent);
  1652.     this.container.appendChild(parent);
  1653.     return parent;
  1654.  
  1655. }
  1656. /**
  1657. *update the line tracker
  1658. **/
  1659. VMLRenderer.prototype.updateLineTracker=function(shape,parent){
  1660.     var screenxdpi=screen.logicalXDPI / 72;
  1661.     vml=parent.getElementsByTagName("oval")[0];
  1662.     var type=this.getConnectorType(shape);
  1663.     var line=this.getShapeSubject(shape);
  1664.     var fromX,fromY=null;
  1665.     if(type=='line'){
  1666.         fromX=line.from.x;
  1667.         fromY=line.from.y;
  1668.     }
  1669.     else if (type=='ortho-line'){
  1670.         fromX=line.points.item(0).x;
  1671.         fromY=line.points.item(0).y;
  1672.     }
  1673.     else if (type=='curve-line'){
  1674.         fromX=line.from.x;
  1675.         fromY=line.from.y;
  1676.         var trackerLine=parent.getElementsByTagName("line")[0];
  1677.         trackerLine.to=fromX+"pt,"+fromY+"pt";
  1678.         
  1679.     }
  1680.     vml.style.left=((parseFloat(fromX) * screenxdpi)-3) + 'px';
  1681.     vml.style.top=((parseFloat(fromY) * screenxdpi)-3) + 'px';    
  1682.         
  1683.     vml.style.zIndex=this.maxIndex+1;
  1684.     vml=parent.getElementsByTagName("oval")[1];
  1685.     var toX,toY=null;
  1686.     if(type=='line'){
  1687.         toX=line.to.x;
  1688.         toY=line.to.y;
  1689.     }
  1690.     else if (type=='ortho-line'){
  1691.         var length=line.points.length;
  1692.         if(length==0)return;
  1693.         var toX=line.points.item(length-1).x;
  1694.         var toY=line.points.item(length-1).y;
  1695.     }
  1696.     else if(type=='curve-line'){
  1697.         toX=line.to.x;
  1698.         toY=line.to.y;
  1699.         var trackerLine=parent.getElementsByTagName("line")[1];
  1700.         trackerLine.to=toX+"pt,"+toY+"pt";
  1701.  
  1702.     }
  1703.     
  1704.     vml.style.left=((parseFloat(toX) * screenxdpi)-3) + 'px';
  1705.     vml.style.top=((parseFloat(toY) * screenxdpi)-3) + 'px';
  1706.     vml.style.zIndex=this.maxIndex+1;
  1707.     //now show the control points!
  1708.     if(type=='curve-line'){
  1709.         vml=parent.getElementsByTagName("oval")[2];
  1710.         toX=line.control1.x;
  1711.         toY=line.control1.y;
  1712.         vml.style.left=((parseFloat(toX) * screenxdpi)-3) + 'px';
  1713.         vml.style.top=((parseFloat(toY) * screenxdpi)-3) + 'px';
  1714.         vml.style.zIndex=this.maxIndex+1;
  1715.         vml.style.visibility="visible";
  1716.         var trackerLine=parent.getElementsByTagName("line")[0];
  1717.         trackerLine.from=toX+"pt,"+toY+"pt";
  1718.         
  1719.         vml=parent.getElementsByTagName("oval")[3];
  1720.         toX=line.control2.x;
  1721.         toY=line.control2.y;
  1722.         vml.style.left=((parseFloat(toX) * screenxdpi)-3) + 'px';
  1723.         vml.style.top=((parseFloat(toY) * screenxdpi)-3) + 'px';
  1724.         var trackerLine=parent.getElementsByTagName("line")[1];
  1725.         trackerLine.from=toX+"pt,"+toY+"pt";
  1726.         vml.style.zIndex=this.maxIndex+1;
  1727.         vml.style.visibility="visible";
  1728.     
  1729.     }
  1730.  
  1731. }
  1732. /*********************end line functions************************************************/
  1733. /**
  1734. *show tracker
  1735. **/
  1736. VMLRenderer.prototype.showTracker = function(shape) {
  1737.   if(!shape)return;
  1738.   if(shape.tagName=="connector"){
  1739.     
  1740.     return this.showLineTracker(shape);
  1741.     
  1742.   }
  1743.   var box = this.bounds(shape);
  1744.   
  1745.   var tracker = document.getElementById('tracker-group');
  1746.   if (tracker) {
  1747.     this.remove(tracker);
  1748.   }
  1749.   var group=this.container.ownerDocument.createElement("v:group");
  1750.   group.id="tracker-group";
  1751.   tracker = this.container.ownerDocument.createElement('v:shape');
  1752.   tracker.id = 'tracker';
  1753.   
  1754.   group.coordsize="1000,1000";
  1755.   group.style.rotation=shape.style.rotation;
  1756.  
  1757.   tracker.style.width=1000;
  1758.   tracker.style.height=1000;
  1759.   tracker.left='0';
  1760.   tracker.top='0'
  1761.   tracker.coordsize="1000,1000";
  1762.   tracker.style.position="absolute";
  1763.   //tracker.style.cursor='e-resize';
  1764.   tracker.setAttribute('filled', 'false');
  1765.   tracker.setAttribute('stroked', 'true');
  1766.   tracker.setAttribute('strokecolor', '#aaaaaa');
  1767.   tracker.setAttribute('strokeweight', '2px');
  1768.   tracker.setAttribute("path","m0,0 l 1000,0,1000,1000,0,1000,0,0 e");
  1769.   //var stroke=this.container.ownerDocument.createElement("v:stroke");
  1770.   //stroke.setAttribute('dashstyle','DashDot');
  1771.   //tracker.appendChild(stroke);
  1772.   
  1773.   
  1774.   
  1775.   group.appendChild(tracker);
  1776.   var width=10*(1000/(box["width"]+50));
  1777.   var height=10*(1000/(box["height"]+50));
  1778.   //now add the right resize
  1779.   var rightstretch=this.container.ownerDocument.createElement("v:rect");
  1780.   rightstretch.coordsize="21600,21600";
  1781.   rightstretch.style.position="absolute";
  1782.   //<v:rect id="resize-right" style="LEFT:950;WIDTH=100;POSITION:relative;top=400;height=100" filled='t' fillcolor="blue"/>
  1783.   rightstretch.id="resize-right";
  1784.   rightstretch.style.left=1000-(width/2);
  1785.   rightstretch.style.width=width;
  1786.   rightstretch.style.position="absolute";
  1787.   rightstretch.style.top=500-(height/2);
  1788.   rightstretch.style.height=height
  1789.   rightstretch.setAttribute('filled', 'true');
  1790.   rightstretch.setAttribute('fillcolor', '#cccccc');
  1791.   group.appendChild(rightstretch);
  1792.   
  1793.   var leftstretch=this.container.ownerDocument.createElement("v:rect");
  1794.   leftstretch.coordsize="21600,21600";
  1795.   leftstretch.style.position="absolute";
  1796.   //<v:rect id="resize-right" style="LEFT:950;WIDTH=100;POSITION:relative;top=400;height=100" filled='t' fillcolor="blue"/>
  1797.   leftstretch.id="resize-left";
  1798.   leftstretch.style.left=-(width/2);
  1799.   leftstretch.style.width=width;
  1800.   leftstretch.style.position="absolute";
  1801.   leftstretch.style.top=500-(height/2);
  1802.   leftstretch.style.height=height;
  1803.   leftstretch.setAttribute('filled', 'true');
  1804.   leftstretch.setAttribute('fillcolor', '#cccccc');
  1805.   group.appendChild(leftstretch);
  1806.   var bottomstretch=this.container.ownerDocument.createElement("v:rect");
  1807.   bottomstretch.coordsize="21600,21600";
  1808.   bottomstretch.style.position="absolute";
  1809.   bottomstretch.id="resize-bottom";
  1810.   bottomstretch.style.left=500-width/2;
  1811.   bottomstretch.style.width=width;
  1812.   bottomstretch.style.position="absolute";
  1813.   bottomstretch.style.top=1000-height/2;
  1814.   bottomstretch.style.height=height;
  1815.   bottomstretch.setAttribute('filled', 'true');
  1816.   bottomstretch.setAttribute('fillcolor', '#cccccc');
  1817.   group.appendChild(bottomstretch);
  1818.   var topstretch=this.container.ownerDocument.createElement("v:rect");
  1819.   topstretch.coordsize="21600,21600";
  1820.   topstretch.style.position="absolute";
  1821.   topstretch.id="resize-top";
  1822.   topstretch.style.left=500-width/2;
  1823.   topstretch.style.width=width
  1824.   topstretch.style.position="absolute";
  1825.   topstretch.style.top=-height/2;
  1826.   topstretch.style.height=height;
  1827.   topstretch.setAttribute('filled', 'true');
  1828.   topstretch.setAttribute('fillcolor', '#cccccc');
  1829.   group.appendChild(topstretch);
  1830.   //<v:oval id="tracker-oval"
  1831.    //fillcolor="blue"
  1832.    //style="position:relative;top:-150;left:450;width:100;height:50;cursor:move">
  1833.    //</v:oval>
  1834.    var rotate=this.container.ownerDocument.createElement("v:oval");
  1835.    rotate.id="tracker-rotate";
  1836.    rotate.style.position="absolute";
  1837.    rotate.style.top=-40*(1000/(box["height"]+30)) ;
  1838.    var rotateWidth=10*(1000/(box["width"]+50));
  1839.    rotate.style.width=rotateWidth;
  1840.    rotate.style.left=500-(rotateWidth/2);
  1841.    rotate.style.height=10*(1000/(box["height"]+50));
  1842.    rotate.style.cursor='move';
  1843.    rotate.setAttribute("filled",'true');
  1844.    rotate.setAttribute("fillcolor",'#cccccc');
  1845.    //todo create a line that goes to the center of the bounding box from the oval
  1846.    //we will not do rotation rigt now, the browser does not seem to be able to handle it too well
  1847.    group.appendChild(rotate);
  1848.    var handles=this.getHandles(shape);
  1849.    for (var i=0;i<handles.length;i++){
  1850.         handles[i].id="tracker-handle:"+i;
  1851.         group.appendChild(handles[i]);
  1852.    }
  1853.    //debugger;
  1854.   group.style.left = box.x - 5;
  1855.   group.style.top = box.y - 5;
  1856.   group.style.width = (box["width"]*1) + 10;
  1857.   group.style.height = (box["height"]*1) + 10;
  1858.   group.style.position="absolute";
  1859.   group.style.zIndex=shape.style.zIndex;
  1860.    group.style.zoom=shape.style.zoom;
  1861.   this.container.appendChild(group);
  1862.   return group;
  1863. }
  1864. /**
  1865. *update the tracker
  1866. *@param the shape
  1867. **/
  1868. VMLRenderer.prototype.updateTracker = function(shape) {
  1869.  
  1870.   var box = this.bounds(shape);
  1871.   
  1872.   var tracker = document.getElementById('tracker-group');
  1873.   if (tracker) {
  1874.     if(shape.tagName=="connector"){
  1875.     
  1876.     return this.updateLineTracker(shape,tracker);
  1877.     
  1878.   }
  1879.     tracker.style.left = box.x - 5;
  1880.     tracker.style.top = box.y - 5;
  1881.     tracker.style.width = (box["width"]*1) + 10;
  1882.     tracker.style.height = (box["height"]*1) + 10;
  1883.     tracker.style.rotation=box.rotation;
  1884.     tracker.style.zIndex=shape.style.zIndex;
  1885.     var rotate= document.getElementById('tracker-rotate');
  1886.     rotate.style.top=-40*(1000/(box["height"]+30)) ;
  1887.     var width=10*(1000/(box["width"]+50));
  1888.     var height=10*(1000/(box["height"]+50));
  1889.     rotate.style.width=width;
  1890.     rotate.style.left=500-(width/2);
  1891.     rotate.style.height=height;
  1892.     var leftstretch= document.getElementById('resize-left');
  1893.     leftstretch.style.left=-(width/2);
  1894.     leftstretch.style.width=width;
  1895.     leftstretch.style.top=500-(height/2);
  1896.     leftstretch.style.height=height;
  1897.     var rightstretch= document.getElementById('resize-right');
  1898.      rightstretch.style.left=1000-(width/2);
  1899.     rightstretch.style.width=width;
  1900.     rightstretch.style.top=500-(height/2);
  1901.     rightstretch.style.height=height
  1902.     var topstretch= document.getElementById('resize-top');
  1903.     topstretch.style.left=500-width/2;
  1904.     topstretch.style.width=width
  1905.     topstretch.style.top=-height/2;
  1906.     topstretch.style.height=height;
  1907.     var bottomstretch= document.getElementById('resize-bottom');
  1908.     bottomstretch.style.left=500-width/2;
  1909.     bottomstretch.style.width=width;
  1910.     bottomstretch.style.position="absolute";
  1911.     bottomstretch.style.top=1000-height/2;
  1912.     bottomstretch.style.height=height;
  1913.     
  1914.     
  1915.   }
  1916.   else{
  1917.     this.showTracker(shape);
  1918. }
  1919. }
  1920.  
  1921.  
  1922. VMLRenderer.prototype.getMarkup = function() {
  1923.   return this.container.innerHTML;
  1924. }
  1925. /**incase of vm the selection source comes back as shape which resides in group/shape, 
  1926. **in order to return group we need to climb 1 level
  1927. **/
  1928. VMLRenderer.prototype.getShapeFromEventSource=function(source){
  1929.     if(source)return source.parentNode;
  1930.  
  1931. }
  1932. /**********************************************begin text rendering algorithms****************************************/
  1933.  
  1934. /**
  1935.  * set the dimensions of the background shape for the connector text
  1936.  * todo, fix visibility here...
  1937.  */
  1938. VMLRenderer.prototype.handleConnectorTextBackgroundPositioning=function(shape,rect,text){
  1939.     var bgShape=this.getConnectorBackgroundShape(shape);
  1940.     shape.appendChild(bgShape);
  1941.     if(text&&trim(text).length>0){
  1942.         this.setX(bgShape,rect.x);
  1943.         this.setY(bgShape,rect.y);
  1944.         this.setWidth(bgShape,rect.width);
  1945.         this.setHeight(bgShape,rect.height);
  1946.     }
  1947.     else{
  1948.         
  1949.         this.hideConnectorBackground(bgShape);
  1950.     }
  1951.     
  1952. }
  1953. /**
  1954.  * hide the connector background, this comes handy when we want to clear the connector text (during moves, resize etc)
  1955.  * or when the text is empty
  1956.  * @param background shape for the connector
  1957.  */
  1958. VMLRenderer.prototype.hideConnectorBackground=function(bgShape){
  1959.     if(bgShape){
  1960.         this.setX(bgShape,0);
  1961.         this.setY(bgShape,0);
  1962.         this.setWidth(bgShape,0);
  1963.         this.setHeight(bgShape,0);
  1964.     }
  1965. }
  1966.  
  1967. /**
  1968.  * handle connector text line positioning
  1969.  * this method will set line positioning for text rendered within connectors
  1970.  */
  1971.  
  1972. VMLRenderer.prototype.handleConnectorTextLinePositioning=function(height,width,x,y,center,fontSize,lines,shapeFont,shape){
  1973.     
  1974.     var centerY=(y*1)+(height*1)/2;
  1975.     var zIndex=this.getShapeSubject(shape).style.zIndex;
  1976.     var shapeArray=new Array();
  1977.     for (var i=center;i>0;i--){
  1978.         var lineTopMargin=(centerY)+((fontSize*1.1)*(i-center));
  1979.         //lineTopMargin=(lineTopMargin*1)+((fontSize)/4);
  1980.         shapeArray[shapeArray.length]=this.createTextShape(lines[i-1],true,0,lineTopMargin,(x*1),(x)+(width*1),shapeFont,zIndex,shape);
  1981.     }
  1982.     for (var i=center;i<lines.length;i++){
  1983.         var lineTopMargin=(centerY)+((fontSize*1.1)*(i+1-center));
  1984.         //lineTopMargin=(lineTopMargin*1)+((fontSize)/4);
  1985.         shapeArray[shapeArray.length]=this.createTextShape(lines[i],true,0,lineTopMargin,(x*1),(x)+(width*1),shapeFont,zIndex,shape);
  1986.     }
  1987.     return shapeArray;
  1988.     
  1989. }
  1990. /**
  1991. *create the text elements and handle text positioning
  1992. **/
  1993. VMLRenderer.prototype.handleTextLinePositioning=function(height,width,x,y,center,fontSize,lines,shapeFont,shape){
  1994.     //if this shape has text bounds, we want to use that for height
  1995.     var textBounds=shape.getElementsByTagName("text-bound");
  1996.     
  1997.     var topMarginBegin=500;
  1998.     var leftMarginBegin=10;
  1999.     var rightMarginEnd=1000;
  2000.     
  2001.     if(textBounds.length>0){
  2002.         height=this.bounds(shape).height;
  2003.         var textb=textBounds[0];
  2004.         var x1=this.getAttribute(textb,"fromX");
  2005.         leftMarginBegin=(leftMarginBegin*1)+(x1*1);
  2006.         var x2=this.getAttribute(textb,"toX");
  2007.         rightMarginEnd=x2-x1;
  2008.         var y1=this.getAttribute(textb,"fromY");
  2009.         var y2=this.getAttribute(textb,"toY");
  2010.         topMarginBegin=(y1*1)+((y2-y1)/2);
  2011.         
  2012.     }
  2013.     var lineHeight=100;
  2014.     //debugger;
  2015.     if(height<=60&&height>=25){
  2016.         lineHeight=((25/(height)+1)*0.9)*(60+(10*(fontSize-10)));
  2017.     }
  2018.     else if(height>60){
  2019.         //if x>100 (25/(x-100))(1/2)*(50+(10*(fontsize-10)))
  2020.         lineHeight=((25/((height)+1))*2.4)*(60+(10*(fontSize-10)));
  2021.     }
  2022.     else if (height<=25){
  2023.         //debugger;
  2024.         lineHeight=((25/(height)+1)*1.3)*(60+(10*(fontSize-10)));
  2025.     }
  2026.     var shapeArray=new Array();
  2027.     for (var i=center;i>0;i--){
  2028.         var lineTopMargin=(topMarginBegin)+((lineHeight+10)*(i-center))+((fontSize-10));
  2029.         var lineHeightMargin=(i-center)*lineHeight;
  2030.         shapeArray[shapeArray.length]=this.createTextShape(lines[i-1],true,lineTopMargin,lineHeightMargin,leftMarginBegin,(rightMarginEnd-10),shapeFont,null,shape);
  2031.     }
  2032.     for (var i=center;i<lines.length;i++){
  2033.         var lineTopMargin=(topMarginBegin)+((lineHeight+10)*(i+1-center))+((fontSize-10));
  2034.         var lineHeightMargin=(i+1-center)*lineHeight;
  2035.         shapeArray[shapeArray.length]=this.createTextShape(lines[i],true,lineTopMargin,lineHeightMargin,leftMarginBegin,(rightMarginEnd-10),shapeFont,null,shape);
  2036.     }
  2037.     return shapeArray;
  2038.     
  2039. }
  2040.  
  2041. /**
  2042. * a utility function to create a text set, sometimes we may need to create a dummy text set (see setShapeText)in which case
  2043. * we need to pass the shape.id as the type in the line object and texpathok=false
  2044. */
  2045. VMLRenderer.prototype.createTextShape
  2046. =function(line,textpathok,lineTopMargin,lineHeightMargin,start,end,shapeFont,zIndex,doc){
  2047.     var doc=this.container.ownerDocument;
  2048.     var shape=null;
  2049.     var path=null;
  2050.     var textPath=null;
  2051.     if(!textpathok){
  2052.         textPath=$("text:template"+line.type);
  2053.     }
  2054.     if(textpathok||!textPath){
  2055.         shape=doc.createElement("v:line");
  2056.         shape.id="text:"+line.type;
  2057.     //shape.style.left=start+"px";
  2058.         shape.style.position="absolute";
  2059.         shape.style.height=50+"px";
  2060.         shape.style.top=lineTopMargin+"px";
  2061.         shape.from=start+","+lineHeightMargin;
  2062.         shape.to=end+","+lineHeightMargin;
  2063.         shape.filled=textpathok;
  2064.         shape.fillcolor=shapeFont.color;
  2065.         shape.stroked=false;//textpathok;
  2066.         shape.strokecolor=shapeFont.color;
  2067.         if(zIndex){
  2068.             shape.style.zIndex=zIndex;
  2069.         }
  2070.         path=doc.createElement("v:path");
  2071.         path.textpathok=textpathok;
  2072.         shape.appendChild(path);
  2073.         textPath=doc.createElement("v:textpath");
  2074.         if(!textpathok){
  2075.             textPath.id="text:template"+line.type;
  2076.         }
  2077.         shape.appendChild(textPath);
  2078.     }
  2079.     else{
  2080.         shape=textPath.parentElement;
  2081.         path=shape.getElementsByTagName("path")[0];
  2082.     }
  2083.     textPath.on=textpathok;
  2084.     textPath.style.fontSize=shapeFont.size;
  2085.     textPath.style.fontWeight=shapeFont.bold;
  2086.     textPath.style.fontFamily=shapeFont.family;
  2087.     shape.style.fontFamily=shapeFont.family;
  2088.     path.style.fontFamily=shapeFont.family;
  2089.     textPath.style.fontStyle=shapeFont.italics;
  2090.     textPath.string=line.text;
  2091.     textPath.style.cssText=textPath.style.cssText+";v-text-align:"+shapeFont.align+";";
  2092.     
  2093.     return shape;
  2094.  
  2095. }
  2096.  
  2097. /**
  2098. *this method should be called only after getShapeText has been called by the editor 
  2099. *to save the text
  2100. */
  2101. VMLRenderer.prototype.clearShapeText=function(shape){
  2102.     var nodes=shape.getElementsByTagName("line");
  2103.     var nodeArray=$A(nodes);
  2104.     var i=0;
  2105.     if(this.isConnector(shape)&&this.getConnectorType(shape)=='line'){
  2106.         i=1;
  2107.     }
  2108.     for(i;i<nodeArray.length;i++){
  2109.         var node=nodeArray[i];
  2110.         if(node.id=="text:normal"||node.id=="text:newline")
  2111.             node.removeNode(true);
  2112.     }
  2113.     if(this.isConnector(shape)){
  2114.         var bgShape=shape.getElementsByTagName("rect");
  2115.         if(bgShape.length>0){
  2116.             this.hideConnectorBackground(bgShape[0]);
  2117.         }
  2118.     }
  2119. }
  2120.  
  2121. /*a utility function to perform word wrap
  2122. * @param m max length of string
  2123. * @param b token to use for each break e.g \n or <br>
  2124. * @param c boolean indicating if hard break should be forced if string longer than m
  2125. * @credits: Jonas Raoni Soares Silva:http://jsfromhell.com/string/wordwrap [v1.0]
  2126. **/
  2127.  
  2128. String.prototype.wordWrap = function(m, b, c){
  2129.     var i, j, l, s, r = this.split("\n");
  2130.     if(m > 0) for(i in r){
  2131.         for(s = r[i], r[i] = ""; s.length > m;
  2132.             j = c ? m : (j = s.substr(0, m).match(/\S*$/)).input.length - j[0].length
  2133.             || m,
  2134.             r[i] += s.substr(0, j) + ((s = s.substr(j)).length ? b : "")
  2135.         );
  2136.         r[i] += s;
  2137.     }
  2138.     return r.join("\n");
  2139. };
  2140.  
  2141.  
  2142. /**
  2143. *utility function to set the fontsize,fontcolor,fontfamily,fontdecoration(bold,italics,underline) and textalign for a given shape
  2144. * if you want to selectively set something e.g size, then only pass size in the font leaving the rest of the stuff as null
  2145. */
  2146. VMLRenderer.prototype.setFont=function(shape,font,zoom){
  2147.     
  2148.     var dummyText=this.getShapeText(shape);
  2149.     //if this is null, then dummy text does not exist
  2150.     //so we have to create one and then we leave
  2151.     if(!dummyText){
  2152.         this.fillUpFont(font);
  2153.         this.setShapeText(shape," ",font,true,null,zoom);
  2154.         return;
  2155.     }
  2156.     //we already have text...now we can start, get the shapes first
  2157.     var nodeList=shape.getElementsByTagName("line");
  2158.     //we will initialize the textpath list later when we need it
  2159.     var textList=new Array();
  2160.     if(font.family!=''||font.bold!=''||font.align!=''||font.italics!=''){
  2161.         for(var i=0;i<nodeList.length;i++){
  2162.             var textPaths=nodeList[i].getElementsByTagName("textpath");
  2163.             if(textPaths.length>0){
  2164.                 textList[textList.length]=textPaths[0];
  2165.             }
  2166.         }
  2167.     }
  2168.     
  2169.     
  2170.     var shapeFont=this.getFont(shape);
  2171.     //if font size changes, we really need to redo the spacing etc.
  2172.     if(font.size!=''&&(font.size!=shapeFont.size)){
  2173.         
  2174.         this.clearShapeText(shape);
  2175.         this.setShapeText(shape,dummyText,font,true,shapeFont,zoom);
  2176.         
  2177.     }
  2178.     //otherwise we will set things individually, no need to create things 
  2179.     if(font.color!=''){
  2180.         //debugger;
  2181.         for(var i=0;i<nodeList.length;i++){
  2182.             if(nodeList[i].id.indexOf("text:")>=0){
  2183.                 nodeList[i].fillcolor=font.color;
  2184.                 nodeList[i].strokecolor=font.color;
  2185.             }
  2186.         }
  2187.     
  2188.     }    
  2189.     //now set the text path specific properties
  2190.     if(font.family!=''){
  2191.     //IE 7.0 follows css 2.1 spec closely, so we need to add the ' around the font name    
  2192.     for(var i=0;i<textList.length;i++){
  2193.             var textItem=textList[i];
  2194.             textItem.style.fontFamily=font.family;
  2195.         }
  2196.     }
  2197.     if(font.bold!=''){
  2198.         for(var i=0;i<textList.length;i++){
  2199.             textList[i].style.fontWeight=font.bold;
  2200.         }
  2201.     }
  2202.     if(font.italics!=''){
  2203.         for(var i=0;i<textList.length;i++){
  2204.             textList[i].style.fontStyle=font.italics;
  2205.         }
  2206.     }
  2207.     if(font.align!=''){
  2208.         //debugger;
  2209.         var re = new RegExp("\\bv-text-align:(\\s)*[a-z]+\\b", "g");
  2210.         for(var i=0;i<textList.length;i++){
  2211.             var textItem=textList[i];
  2212.             textItem.style.cssText=textList[i].style.cssText.replace(re,"v-text-align:"+font.align);
  2213.             var parent=textItem.parentElement;
  2214.             textItem.removeNode(true);
  2215.             parent.appendChild(textItem);
  2216.             
  2217.         }
  2218.         
  2219.     }
  2220.     
  2221.  
  2222. }
  2223. /**
  2224. *this method will pull out the font from the dummyText and then report it back
  2225. **/
  2226.  
  2227. VMLRenderer.prototype.getFont=function(shape){
  2228.  
  2229.     var font=new Object();
  2230.     font.size="16";
  2231.     font.family="'arial'";
  2232.     font.color='black';
  2233.     font.align='center';
  2234.     font.italics='';
  2235.     font.bold='';
  2236.     //for backward compatibility. after 0.2 we will use "text:template";
  2237.     var element=document.getElementById("text:dummy"+shape.id);;
  2238.     if(!element){
  2239.         element=document.getElementById("text:template"+shape.id);
  2240.     }
  2241.     if(!element)
  2242.         return font;
  2243.     else{
  2244.         
  2245.         if(element.parentElement.fillcolor)
  2246.             font.color=element.parentElement.fillcolor.value;
  2247.         if(element.style.fontFamily)
  2248.             font.family=element.style.fontFamily;
  2249.         if(element.style.fontSize)
  2250.             font.size=element.style.fontSize.split("px")[0];
  2251.         if(element.style.fontWeight)
  2252.             font.bold=element.style.fontWeight;
  2253.         if(element.style.fontStyle)
  2254.             font.italics=element.style.fontStyle;
  2255.         //todo for align!!!
  2256.         if(element.style.cssText){
  2257.             var cssText=element.style.cssText;
  2258.             var vAlignIndex=cssText.split("v-text-align:");
  2259.             if(vAlignIndex.length>1){
  2260.                 var vAlignEnd=vAlignIndex[1].split(";");
  2261.                 if(vAlignEnd.length>0){
  2262.                     font.align=trim(vAlignEnd[0]);
  2263.             }
  2264.             }
  2265.         
  2266.         }
  2267.     
  2268.     }
  2269.     return font;    
  2270.  
  2271. }
  2272.  
  2273.  
  2274.  
  2275. /**
  2276. *append an attribute to the page cumulate draw specific
  2277. **/
  2278. VMLRenderer.prototype.appendPageAttribute=function(div,attribute){
  2279.     if(div)div.appendChild(attribute);
  2280.  
  2281. }
  2282. /**
  2283. *return the real data embedded in the richdraw editor
  2284. **/
  2285. VMLRenderer.prototype.getRealData=function(){
  2286.     var div=this.createElement("div");
  2287.     div.insertAdjacentHTML("AfterBegin",this.container.innerHTML);
  2288.     var textElements=div.getElementsByTagName("textpath");
  2289.     
  2290.     for(var i=0;i<textElements.length;i++){
  2291.         if(textElements[i].string){
  2292.             var theString=textElements[i].string;
  2293.             var node=this.container.ownerDocument.createTextNode(theString);
  2294.             textElements[i].appendChild(node);
  2295.             textElements[i].string=null;
  2296.         }
  2297.     }
  2298.     return div;
  2299. }
  2300. /**
  2301. *return the response as a valid xml document, since version 0.3.7 we move the strings in the textpath string
  2302. * attribute into the node to prevent invalid xml
  2303. **/
  2304. VMLRenderer.prototype.getValidDocumentFromResponse=function(response){
  2305.     var div=this.createElement("div");
  2306.     div.innerHTML=response;
  2307.     return div;
  2308. }
  2309.  
  2310. /**
  2311. *open the objects in .mmd file
  2312. **/
  2313. VMLRenderer.prototype.open=function(div){
  2314.     var nodes=this.getAllShapes(div);
  2315.     var nodeArray=$A(nodes);    
  2316.     for(var i=0;i<nodeArray.length;i++){
  2317.         this.container.appendChild(nodeArray[i]);
  2318.         this.updateZIndex(nodeArray[i]);
  2319.     }
  2320.     nodes=this.getAllConnectors(div);
  2321.     nodeArray=$A(nodes);
  2322.     for(var i=0;i<nodeArray.length;i++){
  2323.         var from,to,c1,c2=null;
  2324.         var subject=this.getShapeSubject(nodeArray[i]);
  2325.         
  2326.         
  2327.         //wierd IE bug which needs line zindex to be 0 until its added to the container....
  2328.                 //debugger;
  2329.         var type=this.getConnectorType(nodeArray[i]);
  2330.         var lookup=(type=='line')?'line':'curve';
  2331.         if(type=='ortho-line'){
  2332.             lookup='polyline';
  2333.             //set points to 0,0 for polylines, before we add them
  2334.             nodeArray[i].getElementsByTagName(lookup)[0].points="0,0";
  2335.         }
  2336.         //hack for curve
  2337.         if(type=='curve-line'){
  2338.             
  2339.             
  2340.             from=subject.from;
  2341.             to= subject.to;
  2342.             c1=subject.control1;
  2343.             c2=subject.control2;
  2344.             subject.from="0,0";
  2345.             subject.to="10,10";
  2346.             subject.control1="1,1";
  2347.             subject.control2="1,1";
  2348.         
  2349.         }
  2350.         var zIndex=nodeArray[i].getElementsByTagName(lookup)[0].style.zIndex;
  2351.         nodeArray[i].getElementsByTagName(lookup)[0].style.zIndex=0;
  2352.         
  2353.         this.container.appendChild(nodeArray[i]);
  2354.         //hack for polylines
  2355.         if(type=='ortho-line'){
  2356.             var points=nodeArray[i].getAttribute("polyline-path");
  2357.             nodeArray[i].getElementsByTagName("polyline")[0].points.value=points;
  2358.         }
  2359.         //hack for curve
  2360.         if(type=='curve-line'){
  2361.             
  2362.             subject.from=from;
  2363.             subject.to=to;
  2364.             subject.control1=c1;
  2365.             subject.control2=c2;
  2366.         
  2367.         }
  2368.         nodeArray[i].getElementsByTagName(lookup)[0].style.zIndex=zIndex;
  2369.         this.updateZIndex(nodeArray[i]);
  2370.     }
  2371.  
  2372. }
  2373. /**a utility function to trim strings**/
  2374. function trim(TRIM_VALUE){
  2375.     if(TRIM_VALUE.length < 1){
  2376.     return"";
  2377.     }
  2378.     TRIM_VALUE = RTrim(TRIM_VALUE);
  2379.     TRIM_VALUE = LTrim(TRIM_VALUE);
  2380.     if(TRIM_VALUE==""){
  2381.     return "";
  2382.     }
  2383.     else{
  2384.     return TRIM_VALUE;
  2385.     }
  2386.  
  2387. function RTrim(VALUE){
  2388.     var w_space = String.fromCharCode(32);
  2389.     var v_length = VALUE.length;
  2390.     var strTemp = "";
  2391.     if(v_length < 0){
  2392.     return"";
  2393.     }
  2394.     var iTemp = v_length -1;
  2395.  
  2396.     while(iTemp > -1){
  2397.     if(VALUE.charAt(iTemp) == w_space){
  2398.     }
  2399.     else{
  2400.     strTemp = VALUE.substring(0,iTemp +1);
  2401.     break;
  2402.     }
  2403.     iTemp = iTemp-1;
  2404.  
  2405.     } //End While
  2406.     return strTemp;
  2407.  
  2408. } //End Function
  2409.  
  2410. function LTrim(VALUE){
  2411.     var w_space = String.fromCharCode(32);
  2412.     if(v_length < 1){
  2413.     return"";
  2414.     }
  2415.     var v_length = VALUE.length;
  2416.     var strTemp = "";
  2417.  
  2418.     var iTemp = 0;
  2419.  
  2420.     while(iTemp < v_length){
  2421.     if(VALUE.charAt(iTemp) == w_space){
  2422.     }
  2423.     else{
  2424.     strTemp = VALUE.substring(iTemp,v_length);
  2425.     break;
  2426.     }
  2427.     iTemp = iTemp + 1;
  2428.     } //End While
  2429.     return strTemp;
  2430. } //End Function
  2431.  
  2432.  
  2433.